package com.learn.kotlinlearndemolist.ui

import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.navigation.fragment.NavHostFragment
import com.learn.kotlinlearndemolist.Delegated
import com.learn.kotlinlearndemolist.R
import com.learn.kotlinlearndemolist.Singleton
import com.learn.kotlinlearndemolist.classes.InnerOrOuter
import com.learn.kotlinlearndemolist.classes.Outer
import com.learn.kotlinlearndemolist.coroutinesdemo.testFirst
import com.learn.kotlinlearndemolist.databinding.ActivityMainBinding
import com.learn.kotlinlearndemolist.derived.Derived
import com.learn.kotlinlearndemolist.derived.DerivedOverride
import com.learn.kotlinlearndemolist.interfaces.StudyAndConsider
import com.learn.kotlinlearndemolist.model.*

class MainActivity : AppCompatActivity() {

    companion object {
        const val TAG = "MainActivity"
    }

    private lateinit var mBinding: ActivityMainBinding

    //[0,3]
    var range = 0..3

    //[0,3)
    var rangeTwo = 0 until 3

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        initView()
        initData()
    }

    private fun initView() {
        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment
        val navController = navHostFragment.navController
    }

    private fun initData() {
        testVar()
        val testIf = testIf(1, 2)
        Log.d(TAG, "onCreate: testIf = $testIf")
        val testWhen = testWhen("Tom")
        Log.d(TAG, "onCreate: $testWhen")
        val checkNumber = checkNumber(111)
        Log.d(TAG, "onCreate: $checkNumber")
        testFor()
        testClass()
        testSingleton()
        testList()
        testMap()
        testCollection()
        testJavaApi()
        testLet()
        testWith()
        swap(b = 1000)
        val studyAndConsider = StudyAndConsider()
        studyAndConsider.read()
        //showTestDialog()
    }

    private fun showTestDialog() {
        AlertDialog.Builder(this).apply {
            setTitle("This is a test dialog")
            setMessage("Something should be showing")
            setCancelable(false)
            setPositiveButton("OK") { dialog, _ ->
                dialog.dismiss()
            }
            setNegativeButton("Cancel") { dialog, _ ->
                dialog.dismiss()
            }
            show()
        }
    }

    private fun swap(a: Int = 100, b: Int) {
        Log.d(TAG, "swap: a = $a b = $b")
//        val temp = a
//        a = b
//        b = temp
    }

    private fun testLet() {
        //判空
        val teacher = Teacher(1, "Jack Test")
        teacher.let {
            it.read()
            it.write()
        }
    }

    private fun testWith() {
        var a = 3;
        do {
            Log.d(TAG, "testWith: $a")
        } while (a < 0)
        val text = """
        |多行字符串
        |菜鸟教程
        |多行字符串
        |Runoob
        """.trimMargin()
        Log.e(TAG, "testWith: $text text length ${text.length}")
        val text1 = """
            多行字符串
            菜鸟教程
            多行字符串
            Runoob
            """
        Log.e(TAG, "testWith: $text1 text1 length ${text1.length}")
        val mutableList = mutableListOf("apple", "orange", "pear", "banana", "grape")
        val result = with(StringBuilder()) {
            append("Start add fruit.\n")
            for (fruit in mutableList) {
                append(fruit).append("\n")
            }
            append("end")
            toString()
        }
        Log.d(TAG, "testWith: result = $result")
        val resultRun = StringBuilder().run {
            append("Start add fruit.\n")
            for (fruit in mutableList) {
                append(fruit).append("\n")
            }
            append("end")
            toString()
        }
        Log.d(TAG, "testWith: run result = $resultRun")
        val resultApply = StringBuilder().apply {
            append("Start add fruit.\n")
            for (fruit in mutableList) {
                append(fruit).append("\n")
            }
            append("end")
        }
        Log.d(TAG, "testWith: apply result = $resultApply")

    }

    private fun testJavaApi() {
        Thread {
            Log.d(TAG, "testJavaApi: thread")
        }.start()
    }

    private fun testCollection() {
        val mutableList = mutableListOf("apple", "orange", "pear", "banana", "grape")
        var maxFruitLengthValue = ""
        for (fruit in mutableList) {
            if (fruit.length > maxFruitLengthValue.length) {
                maxFruitLengthValue = fruit
            }
        }
        Log.d(TAG, "testCollection: maxFruitLengthValue = $maxFruitLengthValue")
        val maxOf = mutableList.maxByOrNull { it.length }
        val lambda = { fruit: String -> fruit.length }
        val maxByOrNull = mutableList.maxByOrNull(lambda)
        Log.d(TAG, "testCollection: $maxByOrNull")
        Log.d(TAG, "testCollection: $maxOf")

        val newList = mutableList.filter { it.length > 4 }.map { it.uppercase() }
        Log.d(TAG, "testCollection: $newList")
        val any = mutableList.any { it.length > 4 };
        Log.d(TAG, "testCollection: any length > 4 $any")
        val all = mutableList.all { it.length > 4 };
        Log.d(TAG, "testCollection: all length > 4 $all")

    }

    private fun testMap() {
        val map = HashMap<String, Int>()
        map["first"] = 1
        map["second"] = 2
        map["third"] = 3
        for (mutableEntry in map) {
            Log.d(
                TAG,
                "testMap: mutableEntry key " +
                        "= ${mutableEntry.key} value = ${mutableEntry.value}"
            )
        }
        val mapOf = mapOf("Apple" to 1, "Banana" to 2, "Cap" to 3)

        for (map in mapOf) {
            Log.d(
                TAG,
                "testMap: map key " +
                        "= ${map.key} value = ${map.value}"
            )
        }
        val mutableMap = mutableMapOf("Apple" to 1, "Banana" to 2, "Cap" to 3)
        for ((fruit, num) in mutableMap) {
            Log.d(TAG, "testMap: $fruit number = $num")
        }
    }

    private fun testList() {
        //不可变
        val list = listOf("apple", "orange", "pear", "banana", "grape")
        //可变
        val mutableList = mutableListOf("apple", "orange", "pear", "banana", "grape")
        val mutableListTest = mutableListOf("apple", "orange", "pear")
        mutableList.add("watermelon")
        for (mutableFruit in mutableList) {
            Log.d(TAG, "testList: mutableFruit = $mutableFruit")
        }
        for (fruit in list) {
            Log.d(TAG, "testList: fruit = $fruit")
        }
        //测试复制操作
        mutableList == mutableListTest
        Log.d(TAG, "testList: $mutableListTest")
        Log.d(TAG, "testList: $mutableList")
        val maxByOrNull = list.maxByOrNull { it.length }
        Log.d(TAG, "testList: $maxByOrNull")
        val map = list.map { it.uppercase() }
        Log.d(TAG, "testList: $map")
        val map1 = map.filter { it.length < 5 }.map { it.lowercase() }
        Log.d(TAG, "testList: $map1")
        val any = list.any { it.length < 4 }
        val all = list.all { it.length >= 4 }
        Log.d(TAG, "testList: any result = $any all result = $all")
    }

    private fun testFor() {
        for (i in range) {
            Log.d(TAG, "onCreate: $i")
        }
        for (i in rangeTwo) {
            Log.d(TAG, "onCreate: $i")
        }
        //表示每次执行循环都会i+2
        for (i in rangeTwo step 2) {
            Log.d(TAG, "onCreate: step $i")
        }
        //[5,2]
        for (i in 5 downTo 2) {
            Log.d(TAG, "onCreate: downTo $i")
        }
    }

    private fun testSingleton() {
        Singleton.singletonTest()
    }

    private fun testClass() {
        val person = Person();
        person.age = 22;
        person.name = "Tom"
        person.eat()
        Person.testObject()
        val student = Student()
        student.grade = 20
        student.sno = "116"
        student.say()
        student.learn()
        val doctor = Doctor()
        doctor.doctorLevel = 2
        doctor.doctorName = "Jack"
        val teacher = Teacher(1);
        teacher.name = "test"
        doctor.study = teacher;
        teacher.read()
        Log.d(TAG, "testClass: $doctor")
        Log.d(TAG, "testClass: $teacher")

        val dataBean = DataBean(1, "test data");
        val dataBean1 = DataBean(1, "test data");
        Log.d(TAG, "testClass: $dataBean")
        Log.d(TAG, "testClass: $dataBean == $dataBean1 = " + (dataBean == dataBean1))
        testClasses()
        testDerived()
        testDelegated()
    }

    private fun testDelegated() {
        val delegated = Delegated()
        Log.d(TAG, "testDelegated: ${delegated.lazyValue}")
        Log.d(TAG, "testDelegated: ${delegated.lazyValue}")
        delegated.name = "First"
        delegated.name = "Second"
    }

    private fun testClasses() {
        val foo = InnerOrOuter.Nested().foo()
        Log.d(TAG, "testClasses: $foo")
        val foo1 = Outer().Inner().foo()
        Log.d(TAG, "testClasses: $foo1")
    }

    private fun testDerived() {
        val baseImpl = Derived.BaseImpl(55555)
        Derived.Derived(baseImpl).print()
        val base = DerivedOverride.BaseImpl(55555)
        DerivedOverride.Derived(base).printMsg()
        DerivedOverride.Derived(base).printMsgLine()
        var derived = DerivedOverride.Derived(base)
        derived.printMsgLine()
        println(derived.msg)
    }

    private fun checkNumber(number: Number) = when (number) {
        is Int -> "this is int"
        is Float -> "this is string"
        else -> "this is null"
    }

    private fun testWhen(name: String) =
        when (name) {
            "Tom" -> "This is Tom"
            "Tim" -> "This is Tim"
            "Jack" -> "This is Jack"
            else -> "null"
        }
//
//    private fun testWhen(name: String) =
//        when {
//            name.startsWith("Tom") -> "This is Tom"
//            name == "Tim" -> "This is Tim"
//            name == "Jack" -> "This is Jack"
//            else -> "null"
//        }

//    private fun testIf(num1: Int, num2: Int): Int {
//        var maxNum = 0;
//        maxNum = if (num1 > num2) {
//            num1
//        } else {
//            num2
//        }
//        return maxNum
//    }

    private fun testIf(num1: Int, num2: Int) =
        if (num1 > num2) {
            num1
        } else {
            num2
        }


    private fun testVar() {
        var a = 10;
        a *= 10;
        Log.d(TAG, "test: a = $a")
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            finish();
        }
        return super.onKeyDown(keyCode, event)
    }
}